<template>
    <uploader ref="uploader" :options="options" :autoStart="false" v-if="flag">
        <uploader-unsupport></uploader-unsupport>
        <uploader-drop>
            <uploader-btn :attrs="attrs">
                <i class="icon folder"></i>
                选择文件
            </uploader-btn>
            <button :disabled="disabled" v-if="showsub" class="ui blue tiny button" @click="uploadAll" v-show="button">
                <i class="icon upload"></i>
                上传
            </button>
            <button class="ui red tiny button fl-r" @click="cancelAll" v-show="button">
                <i class="icon trash alternate outline"></i>
                清空
            </button>
        </uploader-drop>
        <uploader-list></uploader-list>
    </uploader>
</template>
<script>
    // 手册 : https://github.com/simple-uploader/Uploader
    import qs from 'qs'

    const UPLOAD_PATH = 'admin/file/uploadFile?'
    const DELETE_PATH = 'admin/file/deleteFile'
    export default {
        name: 'ui-uploader',
        props: {
            url: {
                type: String,
                default: BASE_URL + UPLOAD_PATH
            },
            delUrl: {
                type: String,
                default: BASE_URL + DELETE_PATH
            },
            accept: {
                type: String
            },
            rename: {
                type: String
            },
            params: {
                type: Object
            },
            headerData: {
                type: Object,
                default() {
                    return {}
                }
            },
            showsub: { //是否显示上传按钮
                type: Boolean,
                default: true
            },
            uploadNumber : Number,
            fileSize : {
                type : [String , Number]
            },
            imageWidth : [String,Number],
            imageHeight : [String,Number],
        },
        data() {
            return {
                attrs: {
                    accept: this.accept
                },
                button: false,
                disabled: false,
                uploaderInstance: null,
                optionsTarget: null,
                filesLen: null,
                count: 0,
                flag: true,
            }
        },
        watch: {
            options: { // 当参数变化后重新初始化
                handler(val) {
                    if (val) {
                        this.flag = false
                        setTimeout(() => {
                            this.flag = true
                            this.init()
                        })
                    }
                },
                deep: true
            },
        },
        computed: {
            options() {
                if (this.params && this.params.method && this.params.method.toUpperCase() === 'POST') {
                    return {
                        target: this.url,
                        query: this.params,
                        uploadMethod: "POST",
                        testChunks: false,
                        withCredentials: true,
                        simultaneousUploads: 1,
                        totalChunks: 1,
                        chunkSize: 1024 * 1024 * 1024 * 1024 * 1024
                    }
                }
                return {
                    target: this.params ? this.url + qs.stringify(this.params) : this.url,
                    testChunks: false,
                    withCredentials: true,
                    simultaneousUploads: 1,
                    totalChunks: 1,
                    chunkSize: 1024 * 1024 * 1024 * 1024 * 1024
                }
            },
            // 将filesize转换成kb
            fileSizeKb () {
                return this.sizeTranformKb(this.fileSize)
            }
        },
        mounted() {
            this.init()
        },
        destroyed() {
            const files = this.uploaderInstance.fileList;
            files.forEach((item) => {
                if (item.isUploading()) {
                    this.uploaderInstance.removeFile(item);
                }
            });
        },
        methods: {
            sizeTranformKb (size) {
                if( !size ) return null
                let val = null
                let key = size.toString().replace(/[\d\x20.]/g,'').toUpperCase()
                switch ( key ) {
                    case '' :
                    case 'KB' :  val = parseFloat(size);
                        break
                    case 'MB' : val = parseFloat(size) * 1024
                        break
                }
                return val
            },
            init() {
                this.$nextTick(() => {
                    // 获取上传组件的实例
                    this.uploaderInstance = this.$refs.uploader.uploader;
                    if (this.headerData && JSON.stringify(this.headerData) !== '{}') {
                        this.uploaderInstance.opts.headers = this.headerData
                    }
                    // 监听上传组件提交到vue实例上的列表值
                    this.$watch(
                            () => {
                                return this.$refs.uploader.files
                            },
                            (val) => {

                                this.button = (val.length > 0) // 当提交了文件后才显示按钮
                                this.filesLen = val.length // 需要上传的文件个数

                                let num = 0
                                let inconformitySize = 0
                                let postfixs = this.accept
                                let nameSize = 0

                                // 限制上传文件类型
                                if (val.length > 0 && this.accept !== '*') {
                                    for (let i = 0, len = val.length; i < len; i++) {

                                        this.verifyWidthHeight(val[i])

                                        // 当前文件大于传入的规定大小,获取文件格式化的
                                        if(this.fileSizeKb && this.sizeTranformKb(val[i].getFormatSize()) > this.fileSizeKb) {
                                            inconformitySize++
                                        }
                                        //当有重命名字段，截取再拼接（只能上传一个文件）
                                        if(this.rename){
                                            const str = val[i].name;
                                            const result = str.split(".").pop();
                                            val[i].name =this.rename+'.'+result
                                        }
                                        let suffix = val[i].name.split('.').pop().toLowerCase()
                                        if (postfixs.indexOf(suffix) > -1) {
                                            num++
                                        } else {
                                            break
                                        }

                                        // 名称长度判断
                                        const name = val[i].name.split('.')[0]
                                        if( name.length > 100 ) {
                                            nameSize++
                                        }
                                    }

                                    // 如果文件类型全部匹配就显示上传按钮
                                    this.disabled = !(val.length === num)
                                    if (this.disabled) {
                                        this.$message({
                                            showClose: true,
                                            message: '发现存在不符合规范的上传文件，请按照要求上传！',
                                            type: 'error',
                                            duration: 5000
                                        });
                                    }else if( inconformitySize ) {
                                        this.disabled = true
                                        this.$message({
                                            showClose: true,
                                            message: `文件大于规定大小(${isNaN(this.fileSize) ? this.fileSize : this.fileSize+'KB'})，请重新上传`,
                                            type: 'error',
                                            duration: 5000,
                                            offset: 60
                                        });
                                    }else if(nameSize) {
                                        this.disabled = true
                                        this.$message({
                                            showClose: true,
                                            message: `文件名称不能大于100个字符，请重新上传`,
                                            type: 'error',
                                            duration: 5000,
                                            offset: 60
                                        });
                                    }
                                }

                                // 增加上传文件数限制
                                if(val.length > this.uploadNumber) {
                                    this.disabled = true
                                    this.$message({
                                        showClose: true,
                                        message: '最多只能上传'+this.uploadNumber+'个文件,请删除多于文件',
                                        type: 'error',
                                        duration: 5000
                                    });
                                }
                            }
                    )

                    // 上传成功后给每个上传文件实例添加fid方便后面删除对应文件
                    this.uploaderInstance.on('fileSuccess', (rootFile, file, message) => {
                        try {
                            message = JSON.parse(message);
                            console.log(message);
                        } catch (e) {
                            message = {};
                            console.warn('message[' + message + '] parse failed: ' + e)
                        }

                        if (message.body && message.body.id) {
                            file.fid = message.body.id;
                        }
                    })

                    // 当全部上传成功
                    this.uploaderInstance.on('fileComplete', () => {
                        this.count++
                        if (this.count === this.filesLen) {
                            this.$emit('global:uploadAllfileComplete')
                        }
                    })

                    // 点击文件队列的删除按钮
                    this.uploaderInstance.on('fileRemoved', (file) => {
                        this.removeFile(file)
                    });

                    this.uploaderInstance.on('fileError', (rootFile, file, message) => {
                        this.$emit('global:uploadFileError', message)
                    })
                })
            },
            verifyWidthHeight (file) {
                if(this.imageWidth || this.imageHeight) {
                  const render = new FileReader()
                  render.onload = (e) => {
                      const image = new Image()
                      image.onload = () => {
                          const width = image.width
                          const height = image.height
                          if(this.imageWidth && parseFloat(this.imageWidth) > width ) {
                              this.disabled = true
                              this.$message.error(file.name+'图片宽度小于建议宽度')
                          }
                          if(this.imageHeight && parseFloat(this.imageHeight) > height ) {
                              this.disabled = true
                              // 增加定时器，避免多个message同时出现时，重叠问题
                              setTimeout(() => {
                                this.$message.error(file.name+'图片高度小于建议高度')
                              })
                          }
                      }
                      image.src = e.target.result
                  }
                  render.readAsDataURL(file.file)
                }
            },
            uploadAll() {
                this.uploaderInstance.upload()
            },
            cancelAll() {
                let files = this.uploaderInstance.fileList;
                // 删除界面上文件队列
                for (let i = files.length - 1; i >= 0; i--) {
                    this.uploaderInstance.removeFile(files[i]);
                }
            },
            removeFile(file) {
                // 删除已上传到服务器的文件
                if (file.fid) {
                    this.$http.post(this.delUrl, {id: file.fid}).then(res => {
                        console.log("删除附件成功.", file, res);
                    }, (res) => {
                        console.warn("删除附件失败.", file, res);
                    })
                }
            }
        }
    }
</script>
